//不能使用commonJs的妨害来导入ES module,需要使用dynamic import() 动态引入，在代码中引入，但是要注意这是异步的
// const sync = require("del");

class MyCleanPlugin {
  //如果需要接收参数，那么就需要constructor,不需要接受参数，就不用写了
  constructor(options) {
    this.initialClean = false; //是否进行过清理
    this.previousBuildAssets = [];
  }
  apply(compiler) {
    //这个是在webpack.config.js中配置的输出路径
    this.outputPath = compiler.options.output.path;

    // compiler.hooks.emit.tap("MyCleanPlugin", async (compilation) => {
    compiler.hooks.emit.tapPromise("MyCleanPlugin", async (compilation) => {
      //   compilation.stats.hasError();
      await this.handleInitial();
    });

    compiler.hooks.done.tapPromise("MyCleanPlugin", async (stats) => {
      //   compilation.stats.hasError();

      await this.handleDone(stats);
    });
  }

  async handleInitial() {
    //第一次进来的时候不会执行
    if (this.initialClean) {
      return;
    }

    this.initialClean -= true;
    // 指定目录下的所有文件
    await this.removeFiles(["**/*"]);
  }

  async handleDone(stats) {
    //得到当前这次编译后的资源
    const assetList = Object.keys(stats.compilation.assets);
    //stats.compilation.assets是一个对象
    console.log(assetList, "assetList");

    const beDeleteAssetList = this.previousBuildAssets.filter((preAsset) => {
      //前一次的编译中的资源，在当前编译中不存在
      return !assetList.includes(preAsset);
    });
    //作为下一次编译的“前一次编译的资源"
    this.previousBuildAssets = assetList;

    if (beDeleteAssetList.length) {
      await this.removeFiles(beDeleteAssetList);
    }
  }

  //发现
  async removeFiles(patters) {
    //deleteSync同步删除
    // deleteSync可能会失败，所以要用try catch
    try {
      //动态引入要使用异步，导致removeFiles要变成异步函数，导致handleInitial要变成异步函数，
      //导致compiler.hooks.emit的钩子函数要变成异步函数，所以你会发现tap就不行了
      const { deleteSync } = await import("del");
      const deletedFiles = deleteSync(patters, {
        cwd: this.outputPath, //输入路径
        dryRun: false, //dryRun：true,不会真实的去删除
      });
      console.log(deletedFiles, "deletedFiles");
    } catch (error) {
      return;
    }
  }
}

module.exports = MyCleanPlugin;
